# -*- coding: utf-8 -*-
"""
心理咨询师服务系统 - 验证器
"""

import re
from typing import Dict, List, Any, Optional, Tuple
from .helpers import validate_email, validate_phone


def validate_password_strength(password: str) -> Tuple[bool, str]:
    """验证密码强度
    
    Args:
        password: 密码
    
    Returns:
        (是否有效, 错误信息)
    """
    if not password:
        return False, '密码不能为空'
    
    if len(password) < 6:
        return False, '密码长度至少6个字符'
    
    if len(password) > 128:
        return False, '密码长度不能超过128个字符'
    
    # 检查是否包含常见弱密码
    weak_passwords = [
        '123456', 'password', '123456789', '12345678',
        'qwerty', '123123', '111111', '1234567890'
    ]
    
    if password.lower() in weak_passwords:
        return False, '密码过于简单，请使用更复杂的密码'
    
    # 强密码检查（可选）
    has_upper = bool(re.search(r'[A-Z]', password))
    has_lower = bool(re.search(r'[a-z]', password))
    has_digit = bool(re.search(r'\d', password))
    has_special = bool(re.search(r'[!@#$%^&*(),.?":{}|<>]', password))
    
    strength_score = sum([has_upper, has_lower, has_digit, has_special])
    
    if len(password) >= 8 and strength_score >= 3:
        return True, '密码强度良好'
    elif len(password) >= 6 and strength_score >= 2:
        return True, '密码强度一般'
    else:
        return True, '密码强度较弱，建议包含大小写字母、数字和特殊字符'


def validate_username(username: str) -> Tuple[bool, str]:
    """验证用户名
    
    Args:
        username: 用户名
    
    Returns:
        (是否有效, 错误信息)
    """
    if not username:
        return False, '用户名不能为空'
    
    if len(username) < 3:
        return False, '用户名长度至少3个字符'
    
    if len(username) > 20:
        return False, '用户名长度不能超过20个字符'
    
    # 只允许字母、数字、下划线和中文
    if not re.match(r'^[a-zA-Z0-9_\u4e00-\u9fa5]+$', username):
        return False, '用户名只能包含字母、数字、下划线和中文字符'
    
    # 不能以数字开头
    if username[0].isdigit():
        return False, '用户名不能以数字开头'
    
    # 检查保留用户名
    reserved_usernames = [
        'admin', 'administrator', 'root', 'system', 'api',
        'www', 'mail', 'ftp', 'test', 'guest', 'anonymous'
    ]
    
    if username.lower() in reserved_usernames:
        return False, '该用户名为系统保留，请选择其他用户名'
    
    return True, '用户名格式正确'


def validate_scale_data(data: Dict[str, Any]) -> Tuple[bool, str]:
    """验证量表数据
    
    Args:
        data: 量表数据
    
    Returns:
        (是否有效, 错误信息)
    """
    # 验证基本字段
    required_fields = ['title', 'description', 'category_id']
    for field in required_fields:
        if not data.get(field):
            return False, f'缺少必填字段: {field}'
    
    # 验证标题
    title = data['title'].strip()
    if len(title) < 2:
        return False, '量表标题至少2个字符'
    if len(title) > 200:
        return False, '量表标题不能超过200个字符'
    
    # 验证描述
    description = data['description'].strip()
    if len(description) < 10:
        return False, '量表描述至少10个字符'
    if len(description) > 2000:
        return False, '量表描述不能超过2000个字符'
    
    # 验证分类ID
    try:
        category_id = int(data['category_id'])
        if category_id <= 0:
            return False, '分类ID必须是正整数'
    except (ValueError, TypeError):
        return False, '分类ID格式错误'
    
    # 验证题目数据（如果提供）
    if 'questions' in data:
        questions = data['questions']
        if not isinstance(questions, list):
            return False, '题目数据必须是数组格式'
        
        if len(questions) == 0:
            return False, '至少需要一个题目'
        
        if len(questions) > 500:
            return False, '题目数量不能超过500个'
        
        for i, question in enumerate(questions):
            is_valid, error_msg = validate_question_data(question, i + 1)
            if not is_valid:
                return False, f'第{i + 1}题: {error_msg}'
    
    # 验证计分规则（如果提供）
    if 'scoring_rules' in data:
        scoring_rules = data['scoring_rules']
        if not isinstance(scoring_rules, list):
            return False, '计分规则必须是数组格式'
        
        for i, rule in enumerate(scoring_rules):
            is_valid, error_msg = validate_scoring_rule_data(rule, i + 1)
            if not is_valid:
                return False, f'第{i + 1}个计分规则: {error_msg}'
    
    return True, '量表数据验证通过'


def validate_question_data(data: Dict[str, Any], question_num: int = 1) -> Tuple[bool, str]:
    """验证题目数据
    
    Args:
        data: 题目数据
        question_num: 题目序号
    
    Returns:
        (是否有效, 错误信息)
    """
    # 验证必填字段
    required_fields = ['question_text', 'question_type']
    for field in required_fields:
        if not data.get(field):
            return False, f'缺少必填字段: {field}'
    
    # 验证题目文本
    question_text = data['question_text'].strip()
    if len(question_text) < 5:
        return False, '题目文本至少5个字符'
    if len(question_text) > 1000:
        return False, '题目文本不能超过1000个字符'
    
    # 验证题目类型
    valid_types = ['single_choice', 'multiple_choice', 'scale', 'text']
    if data['question_type'] not in valid_types:
        return False, f'题目类型必须是: {", ".join(valid_types)}'
    
    # 验证选项（选择题必须有选项）
    if data['question_type'] in ['single_choice', 'multiple_choice', 'scale']:
        if 'options' not in data or not data['options']:
            return False, '选择题必须提供选项'
        
        options = data['options']
        if not isinstance(options, list):
            return False, '选项必须是数组格式'
        
        if len(options) < 2:
            return False, '至少需要2个选项'
        
        if len(options) > 20:
            return False, '选项数量不能超过20个'
        
        for i, option in enumerate(options):
            is_valid, error_msg = validate_option_data(option, i + 1)
            if not is_valid:
                return False, f'选项{i + 1}: {error_msg}'
    
    return True, '题目数据验证通过'


def validate_option_data(data: Dict[str, Any], option_num: int = 1) -> Tuple[bool, str]:
    """验证选项数据
    
    Args:
        data: 选项数据
        option_num: 选项序号
    
    Returns:
        (是否有效, 错误信息)
    """
    # 验证必填字段
    required_fields = ['option_text', 'option_value']
    for field in required_fields:
        if field not in data:
            return False, f'缺少必填字段: {field}'
    
    # 验证选项文本
    option_text = str(data['option_text']).strip()
    if len(option_text) < 1:
        return False, '选项文本不能为空'
    if len(option_text) > 200:
        return False, '选项文本不能超过200个字符'
    
    # 验证选项值
    try:
        option_value = float(data['option_value'])
    except (ValueError, TypeError):
        return False, '选项值必须是数字'
    
    return True, '选项数据验证通过'


def validate_scoring_rule_data(data: Dict[str, Any], rule_num: int = 1) -> Tuple[bool, str]:
    """验证计分规则数据
    
    Args:
        data: 计分规则数据
        rule_num: 规则序号
    
    Returns:
        (是否有效, 错误信息)
    """
    # 验证必填字段
    required_fields = ['rule_name', 'rule_type']
    for field in required_fields:
        if not data.get(field):
            return False, f'缺少必填字段: {field}'
    
    # 验证规则名称
    rule_name = data['rule_name'].strip()
    if len(rule_name) < 2:
        return False, '规则名称至少2个字符'
    if len(rule_name) > 100:
        return False, '规则名称不能超过100个字符'
    
    # 验证规则类型
    valid_types = ['sum', 'average', 'weighted_sum', 'custom']
    if data['rule_type'] not in valid_types:
        return False, f'规则类型必须是: {", ".join(valid_types)}'
    
    return True, '计分规则数据验证通过'


def validate_assessment_data(data: Dict[str, Any]) -> Tuple[bool, str]:
    """验证测评数据
    
    Args:
        data: 测评数据
    
    Returns:
        (是否有效, 错误信息)
    """
    # 验证必填字段
    required_fields = ['scale_id', 'answers']
    for field in required_fields:
        if field not in data:
            return False, f'缺少必填字段: {field}'
    
    # 验证量表ID
    try:
        scale_id = int(data['scale_id'])
        if scale_id <= 0:
            return False, '量表ID必须是正整数'
    except (ValueError, TypeError):
        return False, '量表ID格式错误'
    
    # 验证答案数据
    answers = data['answers']
    if not isinstance(answers, list):
        return False, '答案数据必须是数组格式'
    
    if len(answers) == 0:
        return False, '至少需要一个答案'
    
    if len(answers) > 500:
        return False, '答案数量不能超过500个'
    
    for i, answer in enumerate(answers):
        is_valid, error_msg = validate_answer_data(answer, i + 1)
        if not is_valid:
            return False, f'第{i + 1}个答案: {error_msg}'
    
    return True, '测评数据验证通过'


def validate_answer_data(data: Dict[str, Any], answer_num: int = 1) -> Tuple[bool, str]:
    """验证答案数据
    
    Args:
        data: 答案数据
        answer_num: 答案序号
    
    Returns:
        (是否有效, 错误信息)
    """
    # 验证必填字段
    required_fields = ['question_id', 'answer_value']
    for field in required_fields:
        if field not in data:
            return False, f'缺少必填字段: {field}'
    
    # 验证题目ID
    try:
        question_id = int(data['question_id'])
        if question_id <= 0:
            return False, '题目ID必须是正整数'
    except (ValueError, TypeError):
        return False, '题目ID格式错误'
    
    # 验证答案值
    answer_value = data['answer_value']
    if answer_value is None:
        return False, '答案值不能为空'
    
    # 答案值可以是数字、字符串或数组（多选题）
    if isinstance(answer_value, list):
        if len(answer_value) == 0:
            return False, '多选答案至少选择一个选项'
        for value in answer_value:
            if not isinstance(value, (int, float, str)):
                return False, '答案值格式错误'
    elif not isinstance(answer_value, (int, float, str)):
        return False, '答案值格式错误'
    
    return True, '答案数据验证通过'


def validate_basic_info_data(data: Dict[str, Any]) -> Tuple[bool, str]:
    """验证基础信息数据
    
    Args:
        data: 基础信息数据
    
    Returns:
        (是否有效, 错误信息)
    """
    if not isinstance(data, dict):
        return False, '基础信息必须是对象格式'
    
    # 验证常见字段
    if 'age' in data:
        try:
            age = int(data['age'])
            if age < 0 or age > 150:
                return False, '年龄必须在0-150之间'
        except (ValueError, TypeError):
            return False, '年龄格式错误'
    
    if 'gender' in data:
        valid_genders = ['male', 'female', 'other', '男', '女', '其他']
        if data['gender'] not in valid_genders:
            return False, f'性别必须是: {", ".join(valid_genders)}'
    
    if 'email' in data and data['email']:
        if not validate_email(data['email']):
            return False, '邮箱格式错误'
    
    if 'phone' in data and data['phone']:
        if not validate_phone(data['phone']):
            return False, '手机号格式错误'
    
    # 验证字段值长度
    for key, value in data.items():
        if isinstance(value, str) and len(value) > 500:
            return False, f'字段 {key} 的值过长（最大500字符）'
    
    return True, '基础信息数据验证通过'